home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
Stream.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-10
|
13KB
|
778 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "Stream.h"
#include "StreamBuf.h"
#include "FileBuf.h"
#include "Class.h"
#include "String.h"
#include "CType.h"
#include "ObjArray.h"
#include "OrdColl.h"
#include "Error.h"
#include "STREAMFILTERS/HexFilter.h"
#include "STREAMFILTERS/StringFilter.h"
OStream cout(1); // UNIX output Stream 1
OStream cerr(2, 0, 0); // UNIX output Stream 2
IStream cin((int)0, &cout); // UNIX input Stream 0 tied to cout
//---- Stream ------------------------------------------------------------------
Stream::Stream(StreamBuf* s, bool dodelete)
{
bp= s;
delete_StreamBuf= dodelete;
state= _good;
deepclone= FALSE;
it= 0;
}
Stream::~Stream()
{
if (it) {
if (all) {
all->RemovePtr(it);
if (all->Size() <= 0) {
OrdCollection *tmp= all;
all= 0;
delete tmp;
}
}
SafeDelete(it);
}
if (bp) {
bp->Finish();
if (delete_StreamBuf)
delete bp;
bp= 0;
}
}
void Stream::Push(StreamBuf *s)
{
if (s) {
s->SetBaseStream(bp);
bp= s;
}
}
void Stream::Pop()
{
if (bp) {
StreamBuf *oldsb= bp;
oldsb->Finish();
bp= oldsb->GetBaseStream();
state= _good;
delete oldsb;
}
}
long Stream::tell()
{
return bp->tell();
}
//---- Misc --------------------------------------------------------------------
OrdCollection *Stream::all;
ObjArray *Stream::Table()
{
if (it == 0) {
it= new ObjArray(10);
if (all == 0)
all= new OrdCollection;
all->Add(it);
}
return it;
}
int Stream::IndexOfPtr(Object *op)
{
return Table()->IndexOfPtr(op);
}
Object *Stream::At(int ix)
{
return Table()->At(ix);
}
void Stream::AtPut(int ix, Object *op)
{
if (op)
Table()->AtPutAndExpand(ix, op);
}
int Stream::MakeIndex(Object *op)
{
return Table()->Index(op);
}
void Stream::InvalidatePtr(Object *op)
{
if (all && op) {
Iter next(all);
register ObjArray *oa;
int ix;
while (oa= (ObjArray*) next())
if (oa != op)
if ((ix= oa->IndexOfPtr(op)) >= 0)
oa->AtPut(ix, (Object*) 0x01);
}
}
//---- OStream -----------------------------------------------------------------
double OStream::dd;
OStream::OStream(StreamBuf* s, bool dodelete) : Stream(s, dodelete)
{
}
OStream::OStream(int fd) : Stream(new Filebuf(fd), TRUE)
{
}
OStream::OStream(int fd, char *bp, int size) : Stream(new Filebuf(fd, bp, size), TRUE)
{
}
OStream::OStream(int size, char* p) : Stream(new StreamBuf(size, p), TRUE)
{
}
OStream::OStream(char* path) : Stream(new Filebuf(path, output), TRUE)
{
if (! ((Filebuf*)bp)->isopen())
state |= _fail;
}
OStream::~OStream()
{
flush();
}
OStream& OStream::seek(long pos, bool relative)
{
if (pos == 0 && relative)
return *this;
bp->seek(pos, relative);
return *this;
}
long OStream::tell()
{
return bp->tell();
}
OStream& OStream::flush()
{
if (bp)
bp->overflow();
return *this;
}
OStream& OStream::put(char c)
{
if (state == 0)
if (bp->sputc(c) == EOF)
state |= _eof | _fail;
return *this;
}
OStream& OStream::put(u_char b)
{
if (state == 0) {
int c= b;
if (bp->sputc(c) == EOF)
state |= _eof | _fail;
}
return *this;
}
OStream& OStream::form(char* va_(fmt), ...)
{
if (state == 0) {
va_list ap;
va_start(ap,va_(fmt));
char *format= va_(fmt);
char buf[BUFSIZE];
register int ll= (int) vsprintf(buf, format, ap);
if (0 < ll && ll < BUFSIZE) // length
;
else if (buf < (char*)ll && (char*)ll < buf+BUFSIZE) // pointer to trailing 0
ll= (char*)ll - buf;
else
ll= strlen(buf);
write(buf, ll);
va_end(ap);
}
return *this;
}
OStream& OStream::Print(int code, void *vp)
{
register StreamBuf *nbp= bp;
if (state)
return *this;
switch (code) {
case eTNone:
break;
case eTChar:
case eTUChar:
if (nbp->sputc((int)vp) == EOF)
state |= _fail;
break;
case eTShort:
form("%d", (long)vp);
break;
case eTUShort:
form("%u", (u_long)vp);
break;
case eTInt:
form("%d", (long)vp);
break;
case eTUInt:
form("%u", (u_long)vp);
break;
case eTLong:
form("%ld", (long)vp);
break;
case eTULong:
form("%lu", (u_long)vp);
break;
case eTFloat:
case eTDouble:
form("%lg", *((double*)vp));
break;
case eTString:
case eTUString:
if (vp && *((char*)vp))
write((const char*)vp, strlen((char*)vp));
break;
case eTStream:
register StreamBuf* b= ((Stream*)vp)->getsbuf();
register int c= b->sgetc();
while (c != EOF) {
if (nbp->sputc(c) == EOF) {
state|= _fail;
break;
}
c= b->snextc();
}
break;
case eTVoid:
form("0x%08x", vp);
fprintf(stderr, "OStream::Print: void*, be careful\n");
break;
default:
fprintf(stderr, "OStream::Print: unknown code %d\n", code);
break;
}
return *this;
}
int OStream::write(const u_char *s, int n)
{
if (state || n <= 0)
return 0;
int r= bp->sputn((char*)s, n);
if (r != n)
setstate((state_value)(_eof|_fail));
return r;
}
OStream &OStream::PrintString(char *s, int l)
{
if (s == 0) {
(*this) << -1 SP;
} else {
if (l < 0)
l= strlen(s)+1;
(*this) << l SP;
if (0) {
put('[');
write(s, l);
} else {
put('\"');
Push(new StringEncoder);
write(s, l);
Pop();
}
}
return (*this);
}
OStream &OStream::PrintHexString(char *s, int l)
{
if (l < 0)
l= strlen(s)+1;
(*this) << l SP;
put('<');
Push(new HexEncoder(">"));
write(s, l);
Pop();
return (*this);
}
void OStream::PutBigEndian(int bytes, long v)
{
register StreamBuf *nbp= bp;
while (bytes-- > 0)
nbp->sputc((int)((v >> bytes*8) & 0xff));
}
//---- IStream -----------------------------------------------------------------
IStream::IStream(StreamBuf* s, OStream* t, bool dodelete) : Stream(s, dodelete) // bind to buffer
{
tied_to= t;
}
IStream::IStream(int size, char *p) : Stream(new StreamBuf(size, p, size), TRUE) // bind to string
{
tied_to= 0;
}
IStream::IStream(int fd, OStream* t) : Stream(new Filebuf(fd), TRUE) // bind to file
{
tied_to= t;
}
IStream::IStream(char *path) : Stream(new Filebuf(path, input), TRUE) // bind to file
{
tied_to= 0;
if (! ((Filebuf*)bp)->isopen())
state |= _fail;
}
IStream& IStream::seek(long pos, bool relative)
{
if (pos != 0 || !relative)
bp->seek(pos, relative);
return *this;
}
long IStream::tell()
{
return bp->tell();
}
OStream* IStream::tie(OStream* s)
{
OStream* t= tied_to;
tied_to= s;
return t;
}
void IStream::eatwhite()
{
flush();
register StreamBuf *nbp= bp;
register char c= nbp->sgetc();
while (Isspace(zapeof(c)))
c= nbp->snextc();
if (c == EOF)
state |= _eof;
}
int IStream::read(u_char *s, int n)
{
if (state || n <= 0) {
state |= _fail;
return 0;
}
int r= bp->sgetn((char*)s, n);
if (r < n) {
state= _fail | _eof;
}
return r;
}
IStream& IStream::get(char& c) // single character
{
flush();
if (state) {
state |= _fail;
return *this;
}
register tc= bp->sgetc();
if (tc == EOF) {
state |= _fail|_eof;
} else {
c= tc;
bp->stossc();
}
return *this;
}
IStream& IStream::peek(char& c) // single character
{
flush();
if (state) {
state |= _fail;
return *this;
}
register tc= bp->sgetc();
if (tc == EOF) {
state |= _fail|_eof;
} else {
c= tc;
}
return *this;
}
IStream& IStream::peek(u_char &b)
{
flush();
if (state) {
state |= _fail;
return *this;
}
register tc= bp->sgetc();
if (tc == EOF)
state |= _fail|_eof;
else {
b= (u_char) tc;
}
return *this;
}
extern "C" double atof(const char*);
IStream& IStream::Scan(int code, void *vp)
{
register StreamBuf *nbp= bp;
register int c;
register long l= 0;
char buf[256];
register char *s;
int neg= 0;
eatwhite();
if (state) {
state |= _fail;
return *this;
}
c= nbp->sgetc();
if (c == EOF) {
state |= _fail;
return *this;
}
switch (code) {
case eTNone:
break;
case eTChar:
case eTUChar:
if (code == eTChar)
*((char*)vp)= c;
else
*((u_char*)vp)= c;
nbp->stossc();
break;
case eTShort:
case eTUShort:
case eTInt:
case eTUInt:
case eTLong:
case eTULong:
switch (c) {
case '-':
case '+':
neg= c;
c= nbp->snextc();
break;
}
if (Isdigit(c)) {
do {
l= l*10+c-'0';
} while (Isdigit(c= nbp->snextc()));
l= (neg == '-') ? -l : l;
switch (code) {
case eTShort:
*((short*)vp)= (short)l;
break;
case eTUShort:
*((u_short*)vp)= (u_short)l;
break;
case eTInt:
*((int*)vp)= (int)l;
break;
case eTUInt:
*((u_int*)vp)= (u_int)l;
break;
case eTLong:
*((long*)vp)= (long)l;
break;
case eTULong:
*((u_long*)vp)= (u_long)l;
break;
}
} else
state |= _fail;
break;
case eTFloat:
case eTDouble:
s= buf;
switch (c) {
case '-':
case '+':
*s++= c;
c= nbp->snextc();
}
/* get integral part */
while (Isdigit(c)) {
*s++= c;
c= nbp->snextc();
}
/* get fraction */
if (c == '.') {
do {
*s++= c;
c= nbp->snextc();
} while (Isdigit(c));
}
/* get exponent */
if (c == 'e' || c == 'E') {
*s++= c;
switch (c= nbp->snextc()) {
case EOF:
state|= _fail;
return *this;
case '-':
case '+':
*s++= c;
c= nbp->snextc();
}
while (Isdigit(c)) {
*s++= c;
c= nbp->snextc();
}
}
*s= 0;
if (code == eTDouble)
*((double*)vp)= atof(buf);
else
*((float*)vp)= (float) atof(buf);
break;
case eTString:
case eTUString:
s= (char*) vp;
while (!Isspace(c) && c != EOF) {
*s++= c;
c= nbp->snextc();
}
*s= '\0';
break;
case eTStream:
register StreamBuf* b= ((Stream*)vp)->getsbuf();
while (c != EOF) {
if (b->sputc(c) == EOF)
break;
c= nbp->snextc();
}
break;
default:
fprintf(stderr, "IStream::Scan: unknown code %d\n", code);
break;
}
return *this;
}
IStream& IStream::get(
register char* s, // character array to read into
register int len, // size of character array
register char term // character that terminates input
) {
register int c;
register StreamBuf *nbp= bp;
eatwhite();
if (state) {
state |= _fail;
return *this;
}
if ((c= bp->sgetc()) == EOF) {
state |= _fail | _eof;
return *this;
}
while (c != term && c != EOF && len > 1) {
*s++= c;
c= nbp->snextc();
len--;
}
*s= '\0';
if (c == EOF)
state |= _eof;
return *this;
}
IStream& IStream::putback(register char c)
{
bp->sputbackc(c);
return *this;
}
IStream& IStream::get(u_char &b)
{
flush();
if (state) {
state |= _fail;
return *this;
}
register tc= bp->sgetc();
if (tc == EOF)
state |= _fail|_eof;
else {
b= (u_char) tc;
bp->stossc();
}
return *this;
}
long IStream::GetBigEndian(int bytes)
{
register long w= 0;
register int tc;
flush();
if (state || bytes < 1 || bytes > 4) {
state |= _fail;
return 0;
}
while (bytes-- > 0) {
if ((tc= bp->sgetc()) == EOF) {
state |= _fail|_eof;
return 0;
} else {
bp->stossc();
w= w*256 + tc;
}
}
return w;
}
char IStream::GetChar()
{
flush();
if (state) {
state |= _fail;
return 0;
}
register tc= bp->sgetc();
if (tc == EOF) {
state |= _fail|_eof;
} else
bp->stossc();
return tc;
}
u_char IStream::GetByte()
{
u_char b;
flush();
if (state) {
state |= _fail;
return 0;
}
register tc= bp->sgetc();
if (tc == EOF) {
state |= _fail|_eof;
} else {
b= tc;
bp->stossc();
}
return b;
}
u_char IStream::GetHex()
{
char c;
u_long val= 0;
for (int i= 0; i < 2; ) {
get(c);
if (Isxdigit(c)) {
val= val*16 + HexValue(c);
i++;
}
}
return val;
}
IStream &IStream::ReadString(char **s, int *lp)
{
register u_char *p, *pp;
int l;
u_char cc;
(*this) >> l;
if (l < 0) {
if (s)
*s= 0;
if (lp)
*lp= 0;
} else {
(*this) >> cc;
pp= p= new u_char[l];
switch (cc) {
case '[':
read(pp, l);
break;
case '"':
Push(new StringDecoder);
read(pp, l);
Pop();
break;
case '<':
Push(new HexDecoder(">"));
read(pp, l);
Pop();
break;
}
if (s)
*s= (char*)pp;
else
delete pp;
if (lp)
*lp= l;
}
return *this;
}